"""
带可选参数的装饰器

问题：
    你想写一个装饰器，既可以不传参数给它，比如 @decorator ，也可以传递可选参数给它，比如 @decorator(x,y,z) 。
解决方案：
    @logged 装饰器可以同时不带参数或带参数。
"""

import logging
from functools import wraps, partial


def logged(func=None, *, level=logging.DEBUG, name=None, message=None):
    if func is None:
        return partial(logged, level=level, name=name, message=message)

    log_name = name if name else func.__module__
    log = logging.getLogger(log_name)
    log_msg = message if message else func.__name__

    @wraps(func)
    def wrapper(*args, **kwargs):
        log.log(level, log_msg)
        return func(*args, **kwargs)

    return wrapper


@logged
def add(x, y):
    return x + y


@logged(level=logging.INFO, name="user")
def say_hello(name):
    print("hello", name)


def use_logged():
    result = add(1, 1)
    print("1 + 1 = ", result)
    say_hello("Kevin")
    # 输出结果：
    """
    1 + 1 =  2
    hello Kevin
    """


if __name__ == '__main__':
    use_logged()
